package com.electronic.utils;

import com.electronic.enums.AlgorithmEnum;
import com.electronic.gbt.GBT7_1_1.SES_Signature;
import com.electronic.gbt.GBT7_1_2.TBS_Sign;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.jcajce.provider.digest.SHA256;
import org.bouncycastle.jcajce.provider.digest.SM3;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;

/**
 * @Author: IFCA
 * @Description: GBT/38540-2020标准签名
 */
public class GBTSignatureUtil {

    /**
     * 功能描述: 生成签名值
     *
     * @param privateKey 签章者私钥
     * @param tbsSign    签章信息
     */
    public static byte[] buildSignedValue(PrivateKey privateKey, byte[] tbsSign, AlgorithmEnum algorithmEnum) {
        Signature sg = null;
        try {
            sg = Signature.getInstance(algorithmEnum.getSignAlg(), new BouncyCastleProvider());
            sg.initSign(privateKey);
            sg.update(tbsSign);
            //签名值 --> 4.签章者对签章信息进行数字签名，生成签名值
            byte[] p1 = sg.sign();
            return p1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 功能描述: 构造签章结构
     *
     * @param tbsSign     签章信息
     * @param signedValue 签名值
     * @param signCert    签章者证书
     */
    public static SES_Signature buildSESSignature(TBS_Sign tbsSign, byte[] signedValue, Certificate signCert, AlgorithmEnum algorithmEnum) throws CertificateEncodingException {
        //签名算法
        ASN1ObjectIdentifier asn1ObjectIdentifier = null;
        if (AlgorithmEnum.SM3.getSignAlg().equals(algorithmEnum.getSignAlg())) {
            asn1ObjectIdentifier = GMObjectIdentifiers.sm2sign_with_sm3;
        } else {
            asn1ObjectIdentifier = PKCSObjectIdentifiers.sha256WithRSAEncryption;
        }

        // 7.1.1签章数据结构
        SES_Signature signature = new SES_Signature().setToSign(tbsSign)
                .setCert(signCert)
                .setSignatureAlgID(asn1ObjectIdentifier)
                .setSignature(signedValue);
        return signature;
    }

    /**
     * 功能描述: 计算待签名原文摘要
     *
     * @param signData 待签名原文
     */
    public static byte[] buildSignDataDigest(byte[] signData, AlgorithmEnum algorithmEnum) {
        //摘要算法
        MessageDigest externalDigest = null;
        if (AlgorithmEnum.SM3.getHashAlg().equals(algorithmEnum.getHashAlg())) {
            externalDigest = new SM3.Digest();
        } else {
            externalDigest = new SHA256.Digest();
        }
        // 原文杂凑值 --> 2.将待签名原文数据进行杂凑运算，形成原文杂凑值
        return externalDigest.digest(signData);
    }
}
